package thread_safe;

/**
 * 导致线程不安全的根本原因是线程的随机性
 * 1.
 * 1>多个线程操作了同一个变量（共享数据）
 * 2>至少要有一个线程修改了这个变量
 * 只要两个线程不是顺序执行的，就一定有问题
 * 2.join()不能控制线程的中间态
 * 3.通过加锁解决线程不安全的问题
 *   两个线程必须对同一个锁对象进行加锁
 * 4.线程不安全的原因：
 *  1>线程调度的随机性，解决不了
 *  2>多个线程对同一个变量进行修改操作，不一定能解决
 *  3>原子性，针对于共享变量的操作是非原子性的
 *  4>内存可见性：一个线程对于数据的操作，很可能其他线程是无感知的，甚至默写情况下，会被编译器优化成完全看不到
 *     线程更新完数据之后，没有立马更新到主内存
 *     线程立马更新到主内存，但是其他线程没有及时从主内存里读数据
 *  5>指令重排序
 * 编译器会对代码进行一定的优化
 * synchronized,synchronized,synchronized
 * synchronized通过加锁的方式实现了原子性和内存可见性
 * 对于指令重排序有一定的约束
 * volatile不能保证原子性，但是可以保证内存可见性，禁止指令重排序
 * 5.线程安全的三大特性
 *   1>原子性
 *   2>内存可见性
 *   3>指令重排序
 * 6.synchronized不公平锁
 *               刷新内存
 *               可重入（自己不会把自己锁死）
 * 7.同一个实例，不同的同步方法，同时只能有一个执行
 * 8.synchronized不能保证指令重排序，只是有一定的约束
 *
 */
public class Demo2 {
    /*
    private static int count = 0;

    //线程不安全
    //两个线程，各自自增五万，总共十万
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    count++;
                }
            }
        };
        Thread t2 = new Thread() {
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    count++;
                }
            }
        };
        t1.start();
        t2.start();
        //等t1和t2执行完
        t1.join();
        t2.join();
        System.out.println(count);
    }
     */
    private static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        //安全的线程，加锁，synchronized(){}
        Object object=new Object();
        Thread t1 = new Thread() {
            public void run() {
                synchronized (object) {
                    for (int i = 0; i < 50000; i++) {
                        count++;
                    }
                }
            }
        };
        Thread t2 = new Thread() {
            public void run() {
                synchronized (object) {
                    for (int i = 0; i < 50000; i++) {
                        count++;
                    }
                }
            }
        };
        t1.start();
        t2.start();
        //等t1和t2执行完
        t1.join();
        t2.join();
        System.out.println(count);
    }
}
